home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / faster10.zip / src / faster.c next >
C/C++ Source or Header  |  1997-06-04  |  17KB  |  588 lines

  1. /*    
  2.     Faster 1.0
  3.     Copyright (C) 1996 Ching-Chih (Oscar) Chang
  4.     All Rights Reserved
  5.     
  6.     oscarc@divideby0.com
  7.  
  8.     This program is designed to add  the WIDTH and HEIGHT arguments into
  9.     the IMG HTML tag.
  10.  
  11.     You may use this program freely, recompile it for other platforms or
  12.     alter it to your liking.  I do *require* you to state that I am  the
  13.     original author of this program.
  14.     
  15.     As a courtesy, please send me an email about the changes you've made
  16.     or  if you've ported this program to another platform.  The makefile
  17.     you write for  your  platform  could  be  added  to the distribution
  18.     source.
  19.  
  20.     This program is distributed in the hope that it will be useful,  but
  21.     WITHOUT   ANY   WARRANTY;  without  even  the  implied  warranty  of
  22.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  23.  
  24.     In other words, use this at your own risk.  I am not responsible for
  25.     any or all damages that may come from the use of this program.
  26.  
  27.     ( Don't you just love legal  mumbo  jumbo?  Oh well it keeps my butt
  28.     out of jail.  :) )
  29.  
  30. */
  31.  
  32. /*
  33.    The following define statements are OS specific settings that you can 
  34.    change without changing the rest of the source code.
  35. */
  36.  
  37. #define COPYCMD    "copy "        /* the command for COPY (e.g. would be cp for unix)
  38.                                Note: remember to have a space afterwards so it
  39.                                will system() the command correctly
  40.                             */
  41.  
  42. #ifdef __DOS__
  43. #define    MAXFILENAME    128        /* the DOS 8.3 filename and the max path */
  44. #define ALLMASK        "*.*"    /* mask for all files in DOS */
  45. #else
  46. #define    MAXFILENAME    1024    /* OS/2 uses long filenames and I think the max path */
  47. #define ALLMASK        "*"        /* mask for all files in OS/2 */
  48. #endif
  49.  
  50. /*
  51.    End of OS specific defines
  52. */
  53.  
  54. #include <stdlib.h>
  55. #include <stdio.h>
  56. #include <string.h>
  57.  
  58. #ifdef __WATCOMC__
  59. #include <dos.h>
  60. #include <direct.h>
  61. #endif
  62.  
  63. /*
  64.    JPEG Tag names
  65. */
  66. #define M_APP0   0xe0
  67. #define M_SOI    0xd8
  68. #define M_SOF0   0xc0
  69. #define M_SOF1   0xc1
  70. #define M_SOF9   0xc9
  71.  
  72. void printhelp();                    /* prints the help file on how to use this thing */
  73. void backupfile(char *srcfile);        /* backups the file before I mess with it (muhahahah ;) */
  74. void dopath(char *mask);            /* Does all the path/file stuff (is recursive) */
  75. int parsefile(char *filename);        /* The hard stuff, reading in the file,
  76.                                        and parsing the img tags */
  77. unsigned char imgtype(char *filename, unsigned short *width, unsigned short *height);
  78.         /*Opens the file and see what the graphics file type it is
  79.           Returns: 0 for error, 1 for GIF, 2 for JPG, 3 for PNG (added later)
  80.         */
  81. unsigned short get2bytes(FILE *infile);
  82.         /* Get's two bytes from the an open file, the way JPG wants it. */
  83. void memerror(char *error);
  84.         /* Displays the error and quits the program with exit(1); */
  85. /*
  86.    Link List functions and structures
  87. */
  88. struct link
  89.     {
  90.     char *filename;
  91.     struct link *next;
  92.     };
  93.  
  94. void addlink(char *str);/* Adds a link to the end of the list (via linktail) */
  95. int dellink();            /* Deletes the head of the link (via linkhead) */
  96.  
  97. static struct link *linkhead = NULL;    /* link list head */
  98. static struct link *linktail;            /* link list tail */
  99.  
  100. /*
  101.     Switches
  102. */
  103. char upper = 0,
  104.      lower = 1,        /* default is lowercase tags */
  105.      recurse = 0,    /* recurse into directories */
  106.      backup = 0,    /* Backup file */
  107.      deleteWH = 0;    /* delete width and height tags */
  108.  
  109. int main(int argc, char **argv)
  110.     {
  111.     int i = 1;
  112.  
  113.     #ifdef __DOS__
  114.     printf("\nFaster for DOS 1.00");
  115.     #endif
  116.     #ifdef __OS2__
  117.     printf("\nFaster for OS/2 1.00");
  118.     #else
  119.     printf("\nFaster 1.00");
  120.     #endif
  121.     printf("\nCopyright (C) 1996 Ching-Chih (Oscar) Chang\nAll Rights Reserved\n");
  122.  
  123.     if (argc == 1)        /* help screen if no args */
  124.         printhelp();
  125.     else
  126.         {
  127.         while(i < argc && argv[i][0] == '-')    /* while they are options (with -) */
  128.             {
  129.             switch(tolower(argv[i][1]))
  130.                 {
  131.                 case 'u' : upper=1; lower=0; break;        /* use uppercase */
  132.                 case 'l' : lower=1; upper=0; break;        /* use lowercase */
  133.                 case 'b' : backup = 1; break;            /* backup files */
  134.                 case 'r' : recurse = 1; break;            /* recursive */
  135.                 case 'd' : deleteWH = 1; break;            /* delete tags */
  136.                 case '?' :
  137.                 case 'h' : printhelp(); exit(0); break;
  138.                 default  : printf("\nError: Unknown switch %s", argv[i]); 
  139.                            return 1; exit(1); break;
  140.                 }
  141.             i++;    /* go to next argument */
  142.             }
  143.         while(i < argc)        /* go through the rest of the args */
  144.             dopath(argv[i++]);
  145.         }
  146.     return 0;
  147.     }
  148.  
  149. void dopath(char *mask)
  150.     {
  151.     unsigned rc;
  152.     struct find_t fileinfo;
  153.     char *cwd;    /* current working directory */
  154.  
  155.     if(recurse == 1)
  156.         {
  157.         /* get's all directories */
  158.         rc = _dos_findfirst(ALLMASK, _A_SUBDIR, &fileinfo);
  159.         while (rc == 0)        /* does the subdirectories */
  160.             {
  161.             /* Make sure it doesn't process \. or \.. and then only the dirs */
  162.             if(fileinfo.name[0] != '.' && fileinfo.attrib == _A_SUBDIR)
  163.                 {
  164.                 chdir(fileinfo.name);
  165.                 dopath(mask);        /* recurse and do it again baby */
  166.                 chdir("..");        /* go back to starting directory */
  167.                 }
  168.             rc = _dos_findnext(&fileinfo);
  169.             }
  170.         #if defined(__OS2__)
  171.         _dos_findclose(&fileinfo);
  172.         #endif
  173.         }
  174.  
  175.     /* start working on the files in the direcotry */
  176.     rc = _dos_findfirst(mask, _A_NORMAL, &fileinfo);
  177.     while(rc == 0)
  178.         {
  179.         addlink(fileinfo.name);            /* add filename to the linklist */
  180.         rc = _dos_findnext(&fileinfo);
  181.         }
  182.     #if defined(__OS2__)
  183.     _dos_findclose(&fileinfo);
  184.     #endif
  185.  
  186.     if(linkhead != NULL)    /* if not an empty directory */
  187.         {
  188.         cwd = getcwd(NULL, 0);    /* Show the current directory */
  189.         printf("\n%s", cwd);
  190.         free(cwd);
  191.         do {
  192.             printf("\n\t%s",linkhead->filename);    /* show the file beening processed */
  193.             if(backup == 1)
  194.                 backupfile(linkhead->filename);
  195.             parsefile(linkhead->filename);        /* do the hard work and process the thing */
  196.             }while(dellink() == 0);
  197.         }
  198.     }
  199.  
  200. int parsefile(char *filename)
  201.     {
  202.     FILE *htmlfile;
  203.     char *html, *buffer, *src, imgfile[MAXFILENAME];
  204.     char wtext[] = "width=", htext[] = "height=", ltoabuf[4];
  205.     unsigned short width, height, i;
  206.     unsigned long len, bufindex, htmlindex;
  207.  
  208.     imgfile[0] = '\0';
  209.     
  210.     htmlfile = fopen(filename, "r+b");    /* Open the html file */
  211.  
  212.     if (htmlfile == NULL)    /* This doesn't seem to print anything in watcom, weird */
  213.         {
  214.         printf("\nUnable to open file %s", filename);
  215.         return 1;
  216.         }
  217.     
  218.     fseek(htmlfile, 0L, SEEK_END);    /* go to the end of the file to... */
  219.     len = ftell(htmlfile);            /* get the filesize */
  220.     fseek(htmlfile, 0L, SEEK_SET);    /* and then jump back */
  221.  
  222.     html = (char *)malloc(len);        /* allocate memory for file */
  223.     if (html == NULL)
  224.         memerror("Not enough memory for HTML file.");
  225.     buffer = (char *)malloc(len*2);    /* make the work buffer twice as big
  226.                                        I know, not very efficent, but I don't
  227.                                        know how else to calculate how big my 
  228.                                        buffer should be */
  229.     if (html == NULL)
  230.         memerror("Not enough memory for HTML buffer.");
  231.     fread(html, len, 1, htmlfile);    /* read in html file */
  232.     fclose(htmlfile);                /* close file, finished reading it */
  233.  
  234.     unlink(filename);    /* erase the file 
  235.                            Note: instead of just overwriting the file, erasing
  236.                            it first may help some undelete programs 
  237.                         */
  238.     htmlfile = fopen(filename, "w+b");    /* create the file */
  239.     bufindex = htmlindex = 0;            /* reset the buffer indexs */
  240.  
  241.     while(htmlindex < len)
  242.         {
  243.         if(html[htmlindex] == '<')        /* if it's a tag */
  244.             {
  245.             /* copy the '<' over then...
  246.                skip any white space between the '<' and the tag name if any
  247.             */
  248.             do    {
  249.                 buffer[bufindex++] = html[htmlindex++];
  250.                 }while(html[htmlindex] == ' ');
  251.  
  252.             if (strnicmp(html+htmlindex, "img", 3) == 0)    /* if img tag */
  253.                 {
  254. /*
  255.                   printf("\nFound IMG tag");
  256. */
  257.                 while(html[htmlindex] != '>')    /* until end of tag */
  258.                     {
  259.                     /* get other tags that I don't touch */
  260.                     do    {
  261.                         buffer[bufindex++] = html[htmlindex++];
  262.                         }while (html[htmlindex] != ' ' && html[htmlindex]!= '>');
  263.                     
  264.                     /* found source tag (yes there's a space there) */
  265.                     if (strnicmp ( html+htmlindex, " src", 4) == 0)
  266.                         {
  267. /*
  268.                           printf(" and SRC tag");
  269. */
  270.                         /* Find the = so we can get to the filename */
  271.                         do    {
  272.                             buffer[bufindex++] = html[htmlindex++];
  273.                             }while(html[htmlindex] != '=');
  274.                         /* skip any white space */
  275.                         do {
  276.                             buffer[bufindex++] = html[htmlindex++];
  277.                             }while(html[htmlindex] == ' ');
  278.                         /* If the filename is inbetween quotes */
  279.                         if(html[htmlindex] == '"')
  280.                             {
  281.                             /* Get the quote */
  282.                             buffer[bufindex++] = html[htmlindex++];
  283.                             i = 0;
  284.                             do {
  285.                                 /* Copy the filename to imgfile and main buffer */
  286.                                 imgfile[i++] = html[htmlindex];
  287.                                 buffer[bufindex++] = html[htmlindex++];
  288.                                 }while(html[htmlindex] != '"');
  289.                             imgfile[i] = '\0';    /* Null terminate */
  290.                             /* get rid of the closing quote */
  291.                             buffer[bufindex++] = html[htmlindex++];
  292.                             }
  293.                          else    /* no quotes */
  294.                              {
  295.                             i = 0;
  296.                             do {
  297.                                 imgfile[i++] = html[htmlindex];
  298.                                 buffer[bufindex++] = html[htmlindex++];
  299.                                 }while(html[htmlindex] != ' ' && html[htmlindex] != '>');
  300.                             imgfile[i] = '\0';    /* Null terminate */
  301.                             }
  302.                         if(imgfile[0] != '\0')    /* if filename was retrieved */
  303.                             {
  304. /*
  305.                               printf(" %s", imgfile);
  306. */
  307.                             /* see what type of file it
  308.                                and if it returns a non-0 then filetype found
  309.                             */
  310.                             if (imgtype(imgfile, &width, &height) != 0 && deleteWH != 1)
  311.                                 {
  312.                                 if(upper == 1)        /* if they want uppercase */
  313.                                     {                /* Lowercase by default   */
  314.                                     strupr(wtext);
  315.                                     strupr(htext);
  316.                                     }
  317.     
  318.                                 /* copy WIDTH to buffer with space before and after */
  319.                                 buffer[bufindex++] = ' ';
  320.                                 buffer[bufindex] = '\0';    /* make sure it's end of string */
  321.  
  322.                                 strcat(buffer, wtext);        /* copy text over */
  323.  
  324.                                 /* insert WIDTH value here */
  325.                                 ltoa(width, ltoabuf, 10);    /* convert number to text */
  326.                                 strcat(buffer, ltoabuf);
  327.  
  328.                                 /* add letter length */
  329.                                 bufindex += strlen(wtext) + strlen(ltoabuf);
  330.  
  331.                                 /* copy HEIGHT to buffer with space before and after */
  332.                                 buffer[bufindex++] = ' ';
  333.                                 buffer[bufindex] = '\0';    /* make sure it's end of string */
  334.  
  335.                                 strcat(buffer, htext);        /* copy text over */
  336.  
  337.                                 /* insert HEIGHT value here */
  338.                                 ltoa(height, ltoabuf, 10);
  339.                                 strcat(buffer, ltoabuf);
  340.                                 bufindex += strlen(htext) + strlen(ltoabuf);
  341.                                 }
  342.                             }
  343.                         }
  344.                     /* Skips the old width and height tags, if any
  345.                        Also used if deleteWH is set which just erases any W/H tags
  346.                        */
  347.                     if (strnicmp(html+htmlindex, " width", 6) == 0)
  348.                         {
  349.                         do    {
  350.                             htmlindex++;
  351.                             }while(html[htmlindex] != ' ' && html[htmlindex] != '>' );
  352.                         /* one more to get rid of an extra space */
  353.                         }                           
  354.                     if (strnicmp(html+htmlindex, " height", 7) == 0)
  355.                         {
  356.                         do    {
  357.                             htmlindex++;
  358.                             }while(html[htmlindex] != ' ' && html[htmlindex] != '>' );
  359.                         }
  360.                     }
  361.                 }
  362.             }
  363.         buffer[bufindex++] = html[htmlindex++];        /* copy it over */
  364.         }
  365.  
  366.     len = fwrite(buffer, 1, bufindex, htmlfile);
  367.     
  368.     if(len != bufindex)        /* check to make sure all the bytes were written */
  369.         {
  370.         do    {
  371.             printf("\nWrite Error: %d bytes of %d were written!\nEnter alternate path to save file: ");
  372.             /* instead of making a new buffer, I thought I'd just reuse html 
  373.                  since it's not being used anyway. */
  374.             scanf("%s", html);
  375.  
  376.             fclose(htmlfile);
  377.  
  378.             htmlfile = fopen(html, "w+b");
  379.             if(htmlfile != NULL)
  380.                 {
  381.                 len = fwrite(buffer, bufindex, 1, htmlfile);
  382.                 }
  383.             }while(len != bufindex);
  384.         }
  385.  
  386.     /* Clean up    */
  387.     fclose(htmlfile);
  388.     free(html);
  389.     free(buffer);
  390.     return 0;
  391.     }
  392.  
  393. unsigned char imgtype(char *filename, unsigned short *width, unsigned short *height)
  394.     {
  395.     FILE *imgfile;
  396.     unsigned char buffer[16];
  397.     unsigned char rtype = 0;
  398.     unsigned short offset;
  399.  
  400.     imgfile = fopen(filename, "r+b");
  401.     if (imgfile == NULL)
  402.         {
  403.         printf("\n\t\tGraphic file %s not found", filename);
  404.         return 0;
  405.         }
  406.     fread(buffer, 16, 1, imgfile);        /* read a chunk of the header */
  407.     
  408.     if(strnicmp(buffer, "GIF", 3) == 0)    /* if it finds a GIF */
  409.         {
  410. /*
  411.           printf("\nFile %s is a GIF", filename);
  412. */
  413.         rtype = 1;
  414.         offset = 6;        /* offset where GIF w/h is */
  415.  
  416.         fseek(imgfile, offset, SEEK_SET);    /* the 6th byte is where w/h start */
  417.         fread(width, 2, 1, imgfile);    /* read the width */
  418.         fread(height, 2, 1, imgfile);    /* read the height */
  419.         }
  420.     else if(strnicmp(buffer+6,"JFIF",4) == 0)    /* +6 to get the type */
  421.         {
  422. /*
  423.           printf("\nFile %s is a JPG", filename);
  424. */
  425.         offset = buffer[4];        /* Get's the length of the header tag */
  426.         offset <<= 8;            /* width/height isn't in the header so we have */
  427.         offset += buffer[5];    /* to jump around a bit with offset */
  428.  
  429.         fseek(imgfile, 6, SEEK_SET);    /* Get rid of the FF, SOI, FF and APP0 */
  430.         /* Find the right tag (SOF0 or SOF1 or SOF9) */
  431.         do    {
  432.             /* offset should -2 since it includes the length (2 bytes) that 
  433.                we already read in but we need to skip the 0xff that's in 
  434.                front of every tag so we do -2+1 = -1 */
  435.             fseek(imgfile, offset-1, SEEK_CUR);
  436.             rtype = fgetc(imgfile);        
  437. /*            printf("\n%x", rtype);
  438. */    
  439.             offset = get2bytes(imgfile);    /* Get the length of this tag */
  440. /*             printf("\nlen = %d", offset);
  441. */
  442.             }while(rtype != M_SOF0 && rtype != M_SOF1 && rtype != M_SOF9);
  443. /*        printf("\nTag found!");
  444. */
  445.         fseek(imgfile, 1, SEEK_CUR);    /* Skip the data precition, don't need it */
  446.         *height = get2bytes(imgfile);
  447.         *width = get2bytes(imgfile);
  448.  
  449.         rtype = 2;
  450.         }
  451.     else
  452.         {
  453.         rtype = 0;
  454.  
  455.         *width = 0;
  456.         *height = 0;
  457.         }
  458.  
  459.     fclose(imgfile);
  460.     return rtype;
  461.     }
  462.  
  463. unsigned short get2bytes(FILE *infile)
  464.     {
  465.     unsigned long a;
  466.     a = fgetc(infile);
  467.     a <<= 8;
  468.     a += fgetc(infile);
  469.     return a;
  470.     }
  471.  
  472. void backupfile(char *srcfile)
  473.     {
  474.     int ret;
  475.     #ifdef __DOS__
  476.     char *where;
  477.     char dest[13];
  478.     char cp[256];    
  479.     strcpy(dest, srcfile);
  480.     where = strchr(dest, '.');    /* find where the extention is */
  481.     if (where != NULL)            /* Chop it off there */
  482.         *where = '\0';
  483.     #else
  484.     int len;
  485.     char dest[256];
  486.     char cp[1024];    /* I think this is the longest command length
  487.                        anyway it's penty of space for the copy command
  488.                        and two filenames */
  489.  
  490.     strcpy(dest, srcfile);
  491.     len = strlen(dest);
  492.  
  493.     /* If it's gonna exceed the 255 file limit, turnicate it and 
  494.        force the .BAK at the end. */
  495.     if (len > 255-4)
  496.         dest[len - 4] = '\0';
  497.     #endif
  498.  
  499.     strcat(dest,".bak");
  500.     printf("\n\tBacking up file %s to %s\n",srcfile, dest);
  501.     #ifdef __WATCOMC__
  502.     flushall();                /* Needs to flush stdio in watcom or it reads wrong */
  503.     #endif
  504.     strcpy(cp, COPYCMD);    /* copy */
  505.     strcat(cp, srcfile);    /*  src     */
  506.     strcat(cp, " ");        /*  <space> */
  507.     strcat(cp, dest);        /*  dest */
  508.     ret = system(cp);        /* run "copy src dest" */
  509.     if (ret != 0)    /* Handles errors if copy doesn't complete for some reason */
  510.         {
  511.         printf("An error has accord in the copy command of your OS...\nDo you wish to contine with Faster? (y/n)");
  512.         #ifdef __WATCOMC__
  513.         flushall();
  514.         #endif
  515.         getch(ret);
  516.         tolower(ret);
  517.         if (ret == 'n')
  518.             {
  519.             printf("\nQuiting Faster");
  520.             exit(1);
  521.             }
  522.         }
  523.     }
  524.  
  525. void memerror(char *error)
  526.     {
  527.     printf("\nError: %s");
  528.     exit(1);
  529.     }
  530.  
  531. void printhelp()
  532.     {
  533.     printf("\nUsage:\n\tfaster <options> <wildcards> ...\nOptions:\
  534. \n\t-h or -?\tThis help screen\
  535. \n\t-Uppercase\tUppercase Letters (e.g. WIDTH=100 HEIGHT=100)\
  536. \n\t-Lowercase\tLowercase Letters *Default*\
  537. \n\t-Backup\t\tBacks up the orignal files\
  538. \n\t-Recurse\tRecurse into subdirectories\
  539. \n\t-Delete\t\tDelete WIDTH and HEIGHT tags");
  540.     }
  541. /*
  542.    Link list functions
  543. */
  544.  
  545. void addlink(char *str)
  546.     {
  547.     struct link *newlink;
  548.  
  549.     newlink = (struct link *)malloc(sizeof(struct link));
  550.     if(newlink == NULL)
  551.         memerror("Not enough memory for linklist");
  552.  
  553.     newlink->filename = (char *)malloc(strlen(str) + 1);
  554.     if(newlink == NULL)
  555.         memerror("Not enough memory for linklist to filename");
  556.  
  557.     strcpy(newlink->filename, str);
  558.     newlink->next = NULL;
  559.  
  560.     if(linkhead == NULL)        /* speical case for first link */
  561.         {
  562.         linkhead = newlink;
  563.         linktail = linkhead;
  564.         }
  565.     else
  566.         {
  567.         linktail->next = newlink;
  568.         linktail = linktail->next;
  569.         }
  570.     }
  571.  
  572. int dellink()
  573.     {
  574.     struct link *temp;
  575.  
  576.     temp = linkhead->next;    
  577.     
  578.     free(linkhead->filename);        
  579.     free(linkhead);            
  580.     
  581.     linkhead = temp;
  582.     
  583.     if(linkhead != NULL)
  584.         return 0;
  585.     else 
  586.         return 1;
  587.     }
  588.